package threadPool;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author: 李德才
 * @description:
 * @create: 2020-12-19 18:54
 **/
public class T03_ThreadPool {

    public static void main(String[] args) {

        /**
         * @corePoolSize 核心线程数，空闲时不归还
         * @maximumPoolSize 最大线程数，核心线程数不够则可以扩展，线程数不得超过设定的最大线程数
         * @keepAliveTime 指定时间没任务就结束，归还资源
         * @unit 归还时间的单位
         * @workQueue 任务队列，
         * @threadFactory 线程工厂
         * @handler 拒绝策略
         *  JDK 自带四种拒策略
         *   *  new ThreadPoolExecutor.AbortPolicy() 抛出异常
         *   *  new ThreadPoolExecutor.DiscardPolicy() 扔掉，不抛异常
         *   *  new ThreadPoolExecutor.DiscardOldestPolicy() 扔掉排队时间最长的，把新来的补进去，场景多为收到最新的之后，老的就没有意义的情况
         *   *  new ThreadPoolExecutor.CallerRunsPolicy() 由调用者处理
         *
         *     public ThreadPoolExecutor(int corePoolSize,
         *                               int maximumPoolSize,
         *                               long keepAliveTime,
         *                               TimeUnit unit,
         *                               BlockingQueue<Runnable> workQueue,
         *                               ThreadFactory threadFactory,
         *                               RejectedExecutionHandler handler) {
         *
         */


        /**
         * ## 线程池中任务的提交顺序
         * 1、向线程池提交任务时，会首先判断线程池中的线程数是否大于设置的核心线程数，如果不大于，就创建一个核心线程来执行任务。
         * 2、如果大于核心线程数，就会判断缓冲队列是否满了，如果没有满，则放入队列，等待线程空闲时执行任务。
         * 3、如果队列已经满了，则判断是否达到了线程池设置的最大线程数，如果没有达到，就创建新线程来执行任务。
         * 4、如果已经达到了最大线程数，则执行指定的拒绝策略。
         *
         * 所以先提交的任务不一定会先执行，尤其是遇到第三步的情况，后加入的任务反而会优先执行
         * 除非使用的是 newSingleThreadPool 可以做到按线程的先后次序到达执行，遵循FIFO的队列模式。
         * newSingleThreadPool是只有1个工作线程的线程池，后续进来的线程都会进入Queue等待队列中，
         * 当线程池线程空闲的时候先进如等待队列的线程会优先进入工作线程执行任务
         *
         * 另外补一句，提到线程池感觉就是为了优化速度和计算机资源使用之间的一个平衡，
         * 在计算机领域谈到速度就有很多场景是放弃了顺序执行换来的，
         * 因为多线程说白了就是使用多个CPU资源（也可能是一个CPU上的多核），多个CPU资源就不一定保证哪个先执行，或者说是哪个先执行完
         */
        new ThreadPoolExecutor(
                2,//核心线程数
                4, //最大线程数
                60, // 生存时间
                TimeUnit.SECONDS, //生存时间单位
                new ArrayBlockingQueue<>(4), //任务队列
                Executors.defaultThreadFactory(), //线程工厂
                new ThreadPoolExecutor.DiscardOldestPolicy() // 拒绝策略
        );
    }
}
